home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / sbin / dpkg-divert < prev    next >
Encoding:
Text File  |  2007-03-06  |  10.0 KB  |  292 lines

  1. #!/usr/bin/perl --
  2.  
  3. $version="1.13.24"; # This line modified by Makefile
  4. $admindir="/var/lib/dpkg"; # This line modified by Makefile
  5. $dpkglibdir="/usr/lib/dpkg"; # This line modified by Makefile
  6. ($0) = $0 =~ m:.*/(.+):;
  7.  
  8. push (@INC, $dpkglibdir);
  9. require 'dpkg-gettext.pl';
  10. textdomain("dpkg");
  11.  
  12. $enoent=`$dpkglibdir/enoent` || die sprintf(_g("Cannot get ENOENT value from %s: %s"), "$dpkglibdir/enoent", $!);
  13. sub ENOENT { $enoent; }
  14.  
  15. sub version {
  16.     printf _g("Debian %s version %s.\n"), $0, $version;
  17.  
  18.     printf _g("
  19. Copyright (C) 1995 Ian Jackson.
  20. Copyright (C) 2000,2001 Wichert Akkerman.");
  21.  
  22.     printf _g("
  23. This is free software; see the GNU General Public Licence version 2 or
  24. later for copying conditions. There is NO warranty.
  25. ");
  26. }
  27.  
  28. sub usage {
  29.     printf(_g(
  30. "Usage: %s [<option> ...] <command>
  31.  
  32. Commands:
  33.   [--add] <file>           add a diversion.
  34.   --remove <file>          remove the diversion.
  35.   --list [<glob-pattern>]  show file diversions.
  36.   --truename <file>        return the diverted file.
  37.  
  38. Options:
  39.   --package <package>      name of the package whose copy of <file> will not
  40.                              be diverted.
  41.   --local                  all packages' versions are diverted.
  42.   --divert <divert-to>     the name used by other packages' versions.
  43.   --rename                 actually move the file aside (or back).
  44.   --admindir <directory>   set the directory with the diversions file.
  45.   --test                   don't do anything, just demonstrate.
  46.   --quiet                  quiet operation, minimal output.
  47.   --help                   show this help message.
  48.   --version                show the version.
  49.  
  50. When adding, default is --local and --divert <original>.distrib.
  51. When removing, --package or --local and --divert must match if specified.
  52. Package preinst/postrm scripts should always specify --package and --divert.
  53. "), $0);
  54. }
  55.  
  56. $testmode= 0;
  57. $dorename= 0;
  58. $verbose= 1;
  59. $mode='';
  60. $|=1;
  61.  
  62. sub checkmanymodes {
  63.     return unless $mode;
  64.     &badusage(sprintf(_g("two modes specified: %s and --%s"), $_, $mode));
  65. }
  66.  
  67. while (@ARGV) {
  68.     $_= shift(@ARGV);
  69.     last if m/^--$/;
  70.     if (!m/^-/) {
  71.         unshift(@ARGV,$_); last;
  72.     } elsif (m/^--help$/) {
  73.         &usage; exit(0);
  74.     } elsif (m/^--version$/) {
  75.         &version; exit(0);
  76.     } elsif (m/^--test$/) {
  77.         $testmode= 1;
  78.     } elsif (m/^--rename$/) {
  79.         $dorename= 1;
  80.     } elsif (m/^--quiet$/) {
  81.         $verbose= 0;
  82.     } elsif (m/^--local$/) {
  83.         $package= ':';
  84.     } elsif (m/^--add$/) {
  85.         &checkmanymodes;
  86.         $mode= 'add';
  87.     } elsif (m/^--remove$/) {
  88.         &checkmanymodes;
  89.         $mode= 'remove';
  90.     } elsif (m/^--list$/) {
  91.         &checkmanymodes;
  92.         $mode= 'list';
  93.     } elsif (m/^--truename$/) {
  94.         &checkmanymodes;
  95.         $mode= 'truename';
  96.     } elsif (m/^--divert$/) {
  97.         @ARGV || &badusage(sprintf(_g("--%s needs a divert-to argument"), "divert"));
  98.         $divertto= shift(@ARGV);
  99.         $divertto =~ m/\n/ && &badusage(_g("divert-to may not contain newlines"));
  100.     } elsif (m/^--package$/) {
  101.         @ARGV || &badusage(sprintf(_g("--%s needs a <package> argument"), "package"));
  102.         $package= shift(@ARGV);
  103.         $package =~ m/\n/ && &badusage(_g("package may not contain newlines"));
  104.     } elsif (m/^--admindir$/) {
  105.         @ARGV || &badusage(sprintf(_g("--%s needs a <directory> argument"), "admindir"));
  106.         $admindir= shift(@ARGV);
  107.     } else {
  108.         &badusage(sprintf(_g("unknown option \`%s'"), $_));
  109.     }
  110. }
  111.  
  112. $mode='add' unless $mode;
  113.  
  114. open(O,"$admindir/diversions") || &quit(sprintf(_g("cannot open diversions: %s"), $!));
  115. while(<O>) {
  116.     s/\n$//; push(@contest,$_);
  117.     $_=<O>; s/\n$// || &badfmt(_g("missing altname"));
  118.     push(@altname,$_);
  119.     $_=<O>; s/\n$// || &badfmt(_g("missing package"));
  120.     push(@package,$_);
  121. }
  122. close(O);
  123.  
  124. if ($mode eq 'add') {
  125.     @ARGV == 1 || &badusage(sprintf(_g("--%s needs a single argument"), "add"));
  126.     $file= $ARGV[0];
  127.     $file =~ m#^/# || &badusage(sprintf(_g("filename \"%s\" is not absolute"), $file));
  128.     $file =~ m/\n/ && &badusage(_g("file may not contain newlines"));
  129.     -d $file && &badusage(_g("Cannot divert directories"));
  130.     $divertto= "$file.distrib" unless defined($divertto);
  131.     $divertto =~ m#^/# || &badusage(sprintf(_g("filename \"%s\" is not absolute"), $divertto));
  132.     $package= ':' unless defined($package);
  133.     for ($i=0; $i<=$#contest; $i++) {
  134.         if ($contest[$i] eq $file || $altname[$i] eq $file ||
  135.             $contest[$i] eq $divertto || $altname[$i] eq $divertto) {
  136.             if ($contest[$i] eq $file && $altname[$i] eq $divertto &&
  137.                 $package[$i] eq $package) {
  138.                 printf(_g("Leaving \`%s'")."\n", &infon($i)) if $verbose > 0;
  139.                 exit(0);
  140.             }
  141.             &quit(sprintf(_g("\`%s' clashes with \`%s'"), &infoa, &infon($i)));
  142.         }
  143.     }
  144.     push(@contest,$file);
  145.     push(@altname,$divertto);
  146.     push(@package,$package);
  147.     printf(_g("Adding \`%s'")."\n", &infon($#contest)) if $verbose > 0;
  148.     &checkrename($file,$divertto);
  149.     &save;
  150.     &dorename($file,$divertto);
  151.     exit(0);
  152. } elsif ($mode eq 'remove') {
  153.     @ARGV == 1 || &badusage(sprintf(_g("--%s needs a single argument"), "remove"));
  154.     $file= $ARGV[0];
  155.     for ($i=0; $i<=$#contest; $i++) {
  156.         next unless $file eq $contest[$i];
  157.         &quit(sprintf(_g("mismatch on divert-to\n  when removing \`%s'\n  found \`%s'"), &infoa, &infon($i)))
  158.               if defined($divertto) && $altname[$i] ne $divertto;
  159.         &quit(sprintf(_g("mismatch on package\n  when removing \`%s'\n  found \`%s'"), &infoa, &infon($i)))
  160.               if defined($package) && $package[$i] ne $package;
  161.         printf(_g("Removing \`%s'")."\n", &infon($i)) if $verbose > 0;
  162.         $orgfile= $contest[$i];
  163.         $orgdivertto= $altname[$i];
  164.         @contest= (($i > 0 ? @contest[0..$i-1] : ()),
  165.                    ($i < $#contest ? @contest[$i+1..$#contest] : ()));
  166.         @altname= (($i > 0 ? @altname[0..$i-1] : ()),
  167.                    ($i < $#altname ? @altname[$i+1..$#altname] : ()));
  168.         @package= (($i > 0 ? @package[0..$i-1] : ()),
  169.                    ($i < $#package ? @package[$i+1..$#package] : ()));
  170.     $dorename = 1;
  171.         &checkrename($orgdivertto,$orgfile);
  172.         &dorename($orgdivertto,$orgfile);
  173.         &save;
  174.         exit(0);
  175.     }
  176.     printf(_g("No diversion \`%s', none removed")."\n", &infoa) if $verbose > 0;
  177.     exit(0);
  178. } elsif ($mode eq 'list') {
  179.     @ilist= @ARGV ? @ARGV : ('*');
  180.     while (defined($_=shift(@ilist))) {
  181.         s/\W/\\$&/g;
  182.         s/\\\?/./g;
  183.         s/\\\*/.*/g;
  184.         push(@list,"^$_\$");
  185.     }
  186.     $pat= join('|',@list);
  187.     for ($i=0; $i<=$#contest; $i++) {
  188.         next unless ($contest[$i] =~ m/$pat/o ||
  189.                      $altname[$i] =~ m/$pat/o ||
  190.                      $package[$i] =~ m/$pat/o);
  191.         print &infon($i),"\n";
  192.     }
  193.     exit(0);
  194. } elsif ($mode eq 'truename') {
  195.     @ARGV == 1 || &badusage(sprintf(_g("--%s needs a single argument"), "truename"));
  196.     $file= $ARGV[0];
  197.     for ($i=0; $i<=$#contest; $i++) {
  198.     next unless $file eq $contest[$i];
  199.     print $altname[$i], "\n";
  200.     exit(0);
  201.     }
  202.     print $file, "\n";
  203.     exit(0);
  204. } else {
  205.     &quit(sprintf(_g("internal error - bad mode \`%s'"), $mode));
  206. }
  207.  
  208. sub infol {
  209.     return (($_[2] eq ':' ? "local " : length($_[2]) ? "" : "any ").
  210.             "diversion of $_[0]".
  211.             (length($_[1]) ? " to $_[1]" : "").
  212.             (length($_[2]) && $_[2] ne ':' ? " by $_[2]" : ""));
  213. }
  214.  
  215. sub checkrename {
  216.     return unless $dorename;
  217.     ($rsrc,$rdest) = @_;
  218.     (@ssrc= lstat($rsrc)) || $! == &ENOENT ||
  219.         &quit(sprintf(_g("cannot stat old name \`%s': %s"), $rsrc, $!));
  220.     (@sdest= lstat($rdest)) || $! == &ENOENT ||
  221.         &quit(sprintf(_g("cannot stat new name \`%s': %s"), $rdest, $!));
  222.     # Unfortunately we have to check for write access in both
  223.     # places, just having +w is not enough, since people do
  224.     # mount things RO, and we need to fail before we start
  225.     # mucking around with things. So we open a file with the
  226.     # same name as the diversions but with an extension that
  227.     # (hopefully) wont overwrite anything. If it succeeds, we
  228.     # assume a writable filesystem.
  229.     foreach $file ($rsrc,$rdest) {
  230.     if (open (TMP, ">> ${file}.dpkg-devert.tmp")) {
  231.         close TMP;
  232.         unlink ("${file}.dpkg-devert.tmp");
  233.     } elsif ($! == ENOENT) {
  234.         $dorename = !$dorename;
  235.     } else {
  236.         &quit(sprintf(_g("error checking \`%s': %s"), $file, $!));
  237.     }
  238.     }
  239.     if (@ssrc && @sdest &&
  240.         !($ssrc[0] == $sdest[0] && $ssrc[1] == $sdest[1])) {
  241.         &quit(sprintf(_g("rename involves overwriting \`%s' with\n".
  242.               "  different file \`%s', not allowed"), $rdest, $rsrc));
  243.     }
  244. }
  245.  
  246. sub dorename {
  247.     return unless $dorename;
  248.     return if $testmode;
  249.     if (@ssrc) {
  250.         if (@sdest) {
  251.             unlink($rsrc) || &quit(sprintf(_g("rename: remove duplicate old link \`%s': %s"), $rsrc, $!));
  252.         } else {
  253.             rename($rsrc,$rdest) || &quit(sprintf(_g("rename: rename \`%s' to \`%s': %s"), $rsrc, $rdest, $!));
  254.         }
  255.     }
  256. }            
  257.     
  258. sub save {
  259.     return if $testmode;
  260.     open(N,"> $admindir/diversions-new") || &quit(sprintf(_g("create diversions-new: %s"), $!));
  261.     chmod 0644, "$admindir/diversions-new";
  262.     for ($i=0; $i<=$#contest; $i++) {
  263.         print(N "$contest[$i]\n$altname[$i]\n$package[$i]\n")
  264.             || &quit(sprintf(_g("write diversions-new: %s"), $!));
  265.     }
  266.     close(N) || &quit(sprintf(_g("close diversions-new: %s"), $!));
  267.     unlink("$admindir/diversions-old") ||
  268.         $! == &ENOENT || &quit(sprintf(_g("remove old diversions-old: %s"), $!));
  269.     link("$admindir/diversions","$admindir/diversions-old") ||
  270.         $! == &ENOENT || &quit(sprintf(_g("create new diversions-old: %s"), $!));
  271.     rename("$admindir/diversions-new","$admindir/diversions")
  272.         || &quit(sprintf(_g("install new diversions: %s"), $!));
  273. }
  274.  
  275. sub infoa { &infol($file,$divertto,$package); }
  276. sub infon { &infol($contest[$i],$altname[$i],$package[$i]); }
  277.  
  278. sub quit
  279. {
  280.     printf STDERR "%s: %s\n", $0, "@_";
  281.     exit(2);
  282. }
  283.  
  284. sub badusage
  285. {
  286.     printf STDERR "%s: %s\n\n", $0, "@_";
  287.     &usage;
  288.     exit(2);
  289. }
  290.  
  291. sub badfmt { &quit(sprintf(_g("internal error: %s corrupt: %s"), "$admindir/diversions", $_[0])); }
  292.